package org.springblade.common.utils;


import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.alibaba.nacos.shaded.com.google.gson.JsonParser;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Component
public class WxSignatureUtil {
	/**
	 * 授权码发放类型
	 */
	private static final String GRANT_TYPE = "client_credential";
	/**
	 * 授权码类型
	 */
	private static final String TYPE = "agent_config";
	/**
	 * 获取微信 TOKEN 接口
	 */
	private static final String ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
	/**
	 * 获取微信令牌接口
	 */
//	private static final String TICKET_URL = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get";
	private static final String TICKET_URL = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket";
	/**
	 * 请求参数名
	 */
	private static final String ACCESS_TOKEN_KEY = "access_token";
	/**
	 * TICKET_KEY
	 */
	private static final String TICKET_KEY = "ticket";
	/**
	 * JSON 解析
	 */
	private static JsonParser parse = new JsonParser();

	/**
	 * 获取签名
	 * 注意 URL 一定要动态获取，不能 hardcode
	 *
	 * @param url
	 * @return
	 */
	public static Map<String, String> getWechatSignature(String url, String appid, String secret, String ticket) {
		if (StringUtils.isEmpty(ticket)){
			String token = getToken(appid, secret);// 获取token
			ticket = getTicket(token);// 获取ticket
		}

		// 随机字符串
		String nonceStr = UUID.randomUUID().toString();
		// 时间戳
		String timestamp = Long.toString(System.currentTimeMillis() / 1000);
		//注意这里参数名必须全部小写，且必须有序
		String context = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
		//加密
//		String signature = SHA1(context);
		String signature = SHA1New(context);
		//封装
		Map<String, String> result = new HashMap<String, String>();
		result.put("url", url);
		result.put("jsapi_ticket", ticket);
		result.put("nonceStr", nonceStr);
		result.put("timestamp", timestamp);
		result.put("signature", signature);
		result.put("appId", appid);
		return result;
	}

	/**
	 * 获取 token
	 *
	 * @return
	 */
	public static String getToken(String appid, String secret) {
		// https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=&secret=xxxxxxxxx
		String url = ACCESS_TOKEN_URL + "?corpid=" + appid + "&corpsecret=" + secret;
		//请求链接获取token
		String response = httpGetForJson(url);
		return ((JsonObject) parse.parse(response)).get(ACCESS_TOKEN_KEY).getAsString();
	}

	/**
	 * 获取 corpid
	 *
	 * @param token
	 * @return
	 */
	public static String getTicket(String token) {
		//A:获取应用的jsapi_ticket
		// https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=xxxx&type=jsapi
		//获取企业的 jsapi_ticket，
		//B:https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN
		//两者的区别具体去看企业微信官网文档 https://developer.work.weixin.qq.com/document/path/90506
		//应该使用获取企业的jsapi_ticket

		String url = TICKET_URL + "?access_token=" + token;
		//请求链接获取token
		String response = httpGetForJson(url);
		return ((JsonObject) parse.parse(response)).get(TICKET_KEY).getAsString();
	}

	/**
	 * SHA1加密
	 *
	 * @param value
	 * @return
	 */
	public static String SHA1(final String value) {
		MessageDigest digest;
		try {
			digest = MessageDigest.getInstance("SHA-1");
			digest.update(value.getBytes());
			byte messageDigest[] = digest.digest();
			StringBuffer hexString = new StringBuffer();
			for (int i = 0; i < messageDigest.length; i++) {
				String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexString.append(0);
				}
				hexString.append(shaHex);
			}
			return hexString.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return "";
	}


	public static String SHA1New(final String value) {
		try {

			final MessageDigest messageDigest = MessageDigest.getInstance("SHA");
			final byte[] digests = messageDigest.digest(value.getBytes());
			final StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < digests.length; i++) {
				int halfbyte = (digests[i] >>> 4) & 0x0F;
				for (int j = 0; j <= 1; j++) {
					stringBuilder.append(
						((0 <= halfbyte) && (halfbyte <= 9))
							? (char) ('0' + halfbyte)
							: (char) ('a' + (halfbyte - 10)));
					halfbyte = digests[i] & 0x0F;
				}
			}

			return stringBuilder.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return "";
	}


	/**
	 * 发送请求
	 *
	 * @param url
	 * @return
	 */
	public static String httpGetForJson(String url) {
		CloseableHttpClient httpclient = HttpClients.createDefault();
		try {
			// 创建 HTTPGET
			HttpGet httpget = new HttpGet(url);
			// 发送 GET 请求
			CloseableHttpResponse response = httpclient.execute(httpget);
			HttpEntity entity = response.getEntity();
			return entity == null ? "" : EntityUtils.toString(entity);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return "";
	}
}
